const PENDING = 'pending',
    SUCCESS = 'success',
    FAILURE = 'failure';

const toString = Object.prototype.toString,
    isPromiseClone = ins => toString.call(ins).slice(8, -1) === 'PromiseClone';

const parsePromiseResult = (res, thenPromise, resolve, reject) => {

    if (Object.is(res, thenPromise)) {

        reject(new Error('chaining cycle detected in PromiseClone'))

    } else if (res === Object(res)) {

        try {

            let then = res.then;

            if (typeof then === 'function') {

                try {

                    then.call(res, y => {
                        parsePromiseResult(y, thenPromise, resolve, reject);
                    }, n => {
                        reject(n);
                    });

                } catch (err) {
                    reject(err);
                }

            } else {
                resolve(res);
            }

        } catch (err) {

            reject(err);

        }

    } else {

        resolve(res);

    }

}

class PromiseClone {

    constructor(excutor) {

        this.state = PENDING; //初始化状态为等待中
        this.result = void 0; //初始化结果为undefined

        this.onResolvedCallbacks = []; //异步成功函数存储器
        this.onRejectedCallbacks = []; //异步失败函数存储器

        let resolve = value => {
            //如果状态没有变更过，就允许更改状态为成功
            if (this.state === PENDING) {
                this.state = SUCCESS;
                this.result = value;
                this.onResolvedCallbacks.forEach(fn => fn()); //执行所有保存的then成功回调
            }
        }

        let reject = error => {
            //与上同理
            if (this.state === PENDING) {
                this.state = FAILURE;
                this.result = error;
                this.onRejectedCallbacks.forEach(fn => fn()); //与上同理
            }
        }


        try {
            excutor(resolve, reject); //执行执行器函数
        } catch (err) {
            reject(err); //如果报错了，就更该状态失败
        }

    }

    //设置Object.prototype.toString.call()调用时的结果为[object PromiseClone]
    get[Symbol.toStringTag]() {
        return 'PromiseClone';
    }

    then(onresolved, onrejected) {

        //初始化成功和失败回调
        typeof onresolved !== 'function' && (onresolved = value => value);
        typeof onrejected !== 'function' && (onrejected = error => {
            throw error;
        });

        //创建新的PromiseClone实例
        let thenPromise = new PromiseClone((resolve, reject) => {

            let {
                state
            } = this;

            //如果是成功状态，就调用成功回调
            if (state === SUCCESS) {

                setTimeout(() => {

                    try {
                        let res = onresolved(this.result);
                        parsePromiseResult(res, thenPromise, resolve, reject);
                    } catch (err) {
                        reject(err);
                    }

                }, 0);
                return;

            }

            //与上同理
            if (state === FAILURE) {

                setTimeout(() => {

                    try {
                        let res = onrejected(this.result);
                        parsePromiseResult(res, thenPromise, resolve, reject);
                    } catch (err) {
                        reject(err);
                    }

                }, 0);
                return;

            }

            //如果仍处于等待中，就先将成功和失败回调暂存起来
            if (state === PENDING) {

                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {

                        try {
                            let res = onresolved(this.result);
                            parsePromiseResult(res, thenPromise, resolve, reject);
                        } catch (err) {
                            reject(err);
                        }

                    }, 0);
                });

                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {

                        try {
                            let res = onrejected(this.result);
                            parsePromiseResult(res, thenPromise, resolve, reject);
                        } catch (err) {
                            reject(err);
                        }

                    }, 0);
                });

            }


        });

        //返回该PromiseClone实例
        return thenPromise;

    }

    //捕获失败状态，并执行失败回调
    catch (onrejected) {
        return this.then(null, onrejected);
    }

    //返回一个异步成功PromiseClone实例
    static resolve(value) {
        return new PromiseClone((resolve, reject) => {
            resolve(value);
        });
    }

    //返回一个异步失败PromiseClone实例
    static reject(error) {
        return new PromiseClone((resolve, reject) => {
            reject(error);
        });
    }

    //即Promise.all静态方法
    static all(iterable) {

        return new PromiseClone((resolve, reject) => {

            //若interable参数不具备迭代器接口，更改为失败状态
            try {
                iterable = [...iterable];
            } catch (err) {
                reject(err)
            }

            let len = iterable.length;
            //如果数组或类数组为空，就返回一个空数组
            if (len === 0) {
                resolve([]);
                return;
            }

            let arr = [],
                index = 0,
                handleLogic = (i, curItem) => {
                    arr[i] = curItem;
                    if (++index >= len) {
                        resolve(arr);
                    }
                }

            for (let i = 0; i < len; i++) {

                let curItem = iterable[i];

                //如果该项是个PromiseClone实例，就做深层判断，拿到最里层的PromiseClone实例的结果，
                //遇到失败PromiseClone实例或错误抛出时，就更改为失败状态
                if (isPromiseClone(curItem)) {
                    let thenPromise = curItem.then(res => {
                        new PromiseClone((resolve, reject) => {
                            parsePromiseResult(res, thenPromise, resolve, reject);
                        }).then(res => {
                            handleLogic(i, res);
                        }, err => {
                            reject(err);
                        });
                    }, err => {
                        reject(err);
                    });
                } else {
                    handleLogic(i, curItem);
                }

            }

        });

    }

    //即Promise.race静态方法
    static race(iterable) {

        return new PromiseClone((resolve, reject) => {

            try {
                iterable = [...iterable];
            } catch (err) {
                reject(err)
            }

            let len = iterable.length;

            for (let i = 0; i < len; i++) {
                let curItem = iterable[i];
                if (isPromiseClone(curItem)) {
                    //等待解析完curItem（一个Promise实例）后在返回最终结果
                    let thenPromise = curItem.then(res => {
                        parsePromiseResult(res, thenPromise, resolve, reject);
                    }, err => {
                        reject(err);
                    });
                } else {
                    //如果是非Promise，就放到异步的成功Promise中，以防前面的promise先执行顺序的带来的结果错误
                    PromiseClone.resolve(curItem).then(res => {
                        resolve(res)
                    });
                }
            }

        });

    }

}